
//This class is a SIGLETON which is a foundamental design pattern
//created by the "Gang of Four".
//This class will be instantiated only one time.
//This is a lazy singleton.

package HibernateLayer;

import POJOs.SSessionAllocation;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;
import java.util.Timer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 *
 * @author fabiofurlan
 */
public class VGetHibernateSession {

    private static VGetHibernateSession singleton = null;
    public List<SSessionAllocation> mainHSession = null;
    VSessionAllocationServices sessionService = new VSessionAllocationServices();
    private SessionFactory sFactory = null;
    private Timer sessionTimer=new Timer(true);

    private VGetHibernateSession(){
        Configuration cfg;
        SessionFactory sessionFactory;
        ArrayList<SSessionAllocation> mainArrayList= new ArrayList<SSessionAllocation>();
        SSessionAllocation aux;
        int count=0;

        System.out.println("VGetHibernateSession | Construct method | Using default Hibernate Mapping");
        cfg = new Configuration().configure("/HibernateMappings/hibernate.cfg.xml");

        sessionFactory = cfg.buildSessionFactory();
        sFactory=sessionFactory;

        while(count<10){
            aux=new SSessionAllocation(sessionFactory.openSession(),count);
            mainArrayList.add(aux);
            count++;
        }
        mainHSession=mainArrayList;
        sessionTimer.scheduleAtFixedRate(new VSessionTimerTask(), 0, 180000);
    }

    private VGetHibernateSession(String mappingsPackagePath, int countPar){
        Configuration cfg;
        SessionFactory sessionFactory;
        ArrayList<SSessionAllocation> mainArrayList= new ArrayList<SSessionAllocation>();
        SSessionAllocation aux;
        int count=0;

        if(mappingsPackagePath!=null){
            System.out.println("VGetHibernateSession | Construct method | Using customized Hibernate Mapping");
            cfg = new Configuration().configure(mappingsPackagePath);
        }
        else{
            System.out.println("VGetHibernateSession | Construct method | Using default Hibernate Mapping");
            cfg = new Configuration().configure("/HibernateMappings/hibernate.cfg.xml");
        }

        sessionFactory = cfg.buildSessionFactory();
        sFactory=sessionFactory;

       while(count<10){
            aux=new SSessionAllocation(sessionFactory.openSession(),count);
            mainArrayList.add(aux);
            count++;
        }
        mainHSession=mainArrayList;
        sessionTimer.scheduleAtFixedRate(new VSessionTimerTask(), 0, 180000);
    }

    public static VGetHibernateSession getMainHSession() {
        if(singleton==null){
            singleton=new VGetHibernateSession();
        }
        return singleton;
    }

    public static VGetHibernateSession getMainHSession(String mappingsPackagePath, int count) {
        if(singleton==null){
            singleton=new VGetHibernateSession(mappingsPackagePath, count);
        }
        return singleton;
    }

    public synchronized SSessionAllocation allocateSession(){
        Iterator<SSessionAllocation> itera=mainHSession.iterator();
        SSessionAllocation getSession;

        while(itera.hasNext()){
            getSession=itera.next();
            if(!getSession.bool){
                getSession.bool=true;
                System.out.println("VGetHibernateSession | allocateSession | get an existing session!");
                //write the session on db with the new timestamp
                getSession.lastAccess=new Timestamp(System.currentTimeMillis());
                sessionService.createBasicStructure(getSession);
                return getSession;
            }
        }

        System.out.println("VGetHibernateSession | allocateSession | get a new session!");
        getSession=new SSessionAllocation(sFactory.openSession(), mainHSession.size());
        getSession.bool=true;
        mainHSession.add(getSession);
        //write the session on db with the new timestamp
        getSession.lastAccess=new Timestamp(System.currentTimeMillis());
        sessionService.createBasicStructure(getSession);
        return getSession;
    }

    public synchronized void deallocateSession(int index){
        Iterator<SSessionAllocation> itera=mainHSession.iterator();
        List<SSessionAllocation> auxList= sessionService.list();
        Iterator<SSessionAllocation> iteraAux= auxList.iterator();
        SSessionAllocation getSession;

        while(itera.hasNext()){
            getSession=itera.next();

            if(getSession.index==index){
                getSession.bool=false;
                getSession.session.clear();
                getSession.deallocateNotify();
                //i do this while because i need to refresh the id property
                while (iteraAux.hasNext()) {
                    getSession=itera.next();
                }
                if(getSession.index==index){
                    sessionService.delete(getSession.getId());
                }

                System.out.println("VGetHibernateSession | deallocateSession | deallocated session number"+index);
            }
        }
    }
}
